package com.sq.partner.manager.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;

import com.sq.partner.manager.common.Config;
import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.common.Result;
import com.sq.partner.manager.dao.CardInfoDao;
import com.sq.partner.manager.dao.FacadeAppApplicantDao;
import com.sq.partner.manager.dao.FacadeAppFormDao;
import com.sq.partner.manager.dao.FacadeAppFormExtendDao;
import com.sq.partner.manager.dao.FacadeAppInsuredDao;
import com.sq.partner.manager.dao.FacadePaymentDao;
import com.sq.partner.manager.dao.FacadeTempPolicyDao;
import com.sq.partner.manager.mybatis.model.FacadeAppApplicant;
import com.sq.partner.manager.mybatis.model.FacadeAppForm;
import com.sq.partner.manager.mybatis.model.FacadeAppFormExtend;
import com.sq.partner.manager.mybatis.model.FacadeAppInsured;
import com.sq.partner.manager.mybatis.model.FacadeTempPolicy;
import com.sq.partner.manager.mybatis.model.FacadeTransLog;
import com.sq.partner.manager.service.ActirationCardPreviewService;
import com.sq.partner.manager.service.FacadeAppFormService;
import com.sq.partner.manager.service.FacadeTempPolicyService;
import com.sq.partner.manager.service.PayService;
import com.sq.partner.manager.util.DateUtil;
import com.sq.partner.manager.util.FreeMarkerUtil;
import com.sq.partner.manager.util.HttpConnectorUtil;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.StrUtil;

/**
 * 保费试算Service接口
 * 
 * @author zhouxiuxiu
 *
 */
@Service
public class ActirationCardPreviewServiceImpl implements
        ActirationCardPreviewService {
    private static Logger logger = LogUtil
            .getLog(ActirationCardPreviewServiceImpl.class);
    @Resource
    private FacadeTempPolicyDao facadeTempPolicyDao;
    @Resource
    private FacadeAppFormDao facadeAppFormDao;
    @Resource
    private FacadeAppInsuredDao facadeAppInsuredDao;
    @Resource
    private FacadeAppFormExtendDao facadeAppFormExtendDao;
    @Resource
    private FacadePaymentDao facadePayDao;
    @Resource
    private FacadeAppApplicantDao facadeAppApplicantDao;
    @Resource
    private FacadeTempPolicyService facadeTempPolicyService;
    @Resource
    private PayService payService;
    @Resource
    private FacadeAppFormService facadeAppFormService;
    @Resource
    private CardInfoDao cardInfoDao;

    /**
     * 保费试算
     * 
     * @param facadeTempPolicy
     * @param facadeuser
     * @throws Exception
     */
    @Override
    public Result computeFee(String cardNo, FacadeTempPolicy facadeTempPolicy)
            throws Exception {
        logger.info("暂存单:[" + facadeTempPolicy.getStagNo() + "]计算保费开始");
        FacadeTempPolicy sfacadeTempPolicy = new FacadeTempPolicy();
        sfacadeTempPolicy.setStagNo(facadeTempPolicy.getStagNo());
        // 查询状态为录入状态的暂存单
        sfacadeTempPolicy.setStatus("01");
        // 根据暂存单号查出暂存单
        facadeTempPolicy = facadeTempPolicyService
                .findFacadeTempPolicy(sfacadeTempPolicy);
        if (facadeTempPolicy == null) {
            return Result.error("暂存单号错误");
        }
        String statusCode = "0000";// 成功返回状态
        String policyType = facadeTempPolicy.getProdType();
        if (StrUtil.isNotEmpty(policyType)) {
            if (Constants.PROD_TYPE_NLIFE.equals(policyType)) { // 新意健险
                statusCode = "00";
            }
        }
        FacadeAppForm sfacadeAppForm = new FacadeAppForm();
        // 计算保费要重新计算为为录入和待支付的保单
        sfacadeAppForm.setStatus("01,11");
        sfacadeAppForm.setStagNo(facadeTempPolicy.getStagNo());
        List<FacadeAppForm> facadeAppForms = facadeAppFormDao
                .selectFacadeAppFormList(sfacadeAppForm);
        // 计算保费入库
        StringBuffer serrInfo = new StringBuffer();
        boolean flag = true;
        // 总金额
        BigDecimal totpremamt = new BigDecimal(Double.toString(0.00));
        String warnInfo="";
        // 保费接口重新调用
        for (int i = 0; i < facadeAppForms.size(); i++) {

            FacadeAppForm facadeAppForm = facadeAppForms.get(i);
            if (cardNo == null) {
                // 根据暂存单号和投保单号取得卡单信息
                cardNo = cardInfoDao.getCardNoByAppNo(
                        facadeAppForm.getAppNo(), facadeTempPolicy.getStagNo());
            }
            if (("01").equals(facadeAppForm.getStatus())) {
                facadeAppForm = calculateFee(cardNo, facadeAppForm);
                String resultCode = facadeAppForm.getResultCode();
                if (!statusCode.equals(resultCode)) {
                    flag = false;
                    String errInfo = facadeAppForm.getErrInfo();
                    serrInfo.append("投保单：" + (i + 1) + "核保失败," + errInfo
                            + "<br>");
                    continue;
                }
                if(facadeAppForm.getWarnInfo()!=null&&!"".equals(facadeAppForm.getWarnInfo())){
                	warnInfo=facadeAppForm.getWarnInfo();
                }
            }
            // 状态为核保成功待支付是计算总保费
            totpremamt = totpremamt.add(facadeAppForm.getTotPremamt());
        }

        if (flag) {
            FacadeTempPolicy uFacadeTempPolicy = new FacadeTempPolicy();
            uFacadeTempPolicy.setStagNo(facadeTempPolicy.getStagNo());
            uFacadeTempPolicy.setUpdateTime(DateUtil.getNowTimestamp());
            uFacadeTempPolicy.setAmount(totpremamt);
            facadeTempPolicyDao.updateTempPolicyNotNull(uFacadeTempPolicy);
            logger.info("暂存单:[" + facadeTempPolicy.getStagNo()
                    + "]保费计算成功,保费为:[" + totpremamt + "]");
        } else {
            return Result.error(serrInfo.toString());
        }
       if("".endsWith(warnInfo)){
    	   return Result.success("保费计算成功");
       }else{
    	   return Result.success("保费计算成功",warnInfo);
       }
        

    }

    /**
     * 调用保费计算接口
     * 
     * @param facadeAppForm
     * @return
     * @throws Exception
     */
    private FacadeAppForm calculateFee(String cardNo, FacadeAppForm facadeAppForm)
            throws Exception {
        if (null == facadeAppForm || !facadeAppForm.getStatus().equals("01")) {
            return null;
        }
        // 默认缺省指定新意健险
        String trialUrl = Constants.NLIFE_TRIAL_URL;
        String trialTemplates = Constants.NLIFE_T1010_TEMPLATES;
        String statusCode = Constants.NLIFE_STATUS_CODE;// 成功返回状态
        // FacadeTempPolicy facadeTempPolicy= facadeTempPolicyService
        // .getFacadeTempPolicy(facadeAppForm.getStagNo());
        // String policyType=facadeTempPolicy.getProdType();
        String transCode = Constants.GW_CH_TX_1010;
        // 加载暂存单表
        Map<String, String> backMessage = null;
        FacadeTransLog facadeTransLog = null;
        // 生成发送报文
        String responseXml = "";
        try {
            facadeTransLog = new FacadeTransLog();
            logger.info("投保单:[" + facadeAppForm.getAppNo() + "]保费计算处理开始");
            Map<String, Object> map = createFacadeAppForm(facadeAppForm);
            facadeAppForm.setStringEffDate(DateUtil.format(
                    facadeAppForm.getEffDate(), "yyyy-MM-dd")
                    + " "
                    + (facadeAppForm.getEffHours() == null ? "00"
                            : facadeAppForm.getEffHours() + ":00:00"));
            facadeAppForm.setStringTermDate(DateUtil.format(
                    facadeAppForm.getTermDate(), "yyyy-MM-dd")
                    + " "
                    + (facadeAppForm.getTermHours() == null ? "00"
                            : facadeAppForm.getTermHours() + ":00:00"));
            facadeAppForm.setUrlApp_No(facadeAppForm.getAppNo());
            // 生成交易流水id
            String transNo = payService
                    .generateTradingSerialNumber(facadeAppForm.getAppNo());
            // 装配校验数据
            FacadeAppFormExtend facadeAppFormExtend = facadeAppFormExtendDao
                    .queryFacadeAppFormExtend(facadeAppForm.getAppNo());
            map.put("facadeAppForm", facadeAppForm);
            map.put("SERIALNUMBER", transNo);
            map.put("facadeAppFormExtend", facadeAppFormExtend);
//            map.put("ANESTHTYPE",
//                    extend == null ? "" : extend.getAnesthType());
            map.put("cardNo", cardNo);
            String requestXml = FreeMarkerUtil.process(
                    Config.getProp(trialTemplates), map);
            logger.info("请求报文生成成功  " + requestXml);
            // 发送请求时插入交易表
            facadeTransLog.setTransNo(transNo);
            facadeTransLog.setTransCode(transCode);
            facadeTransLog.setStagNo(facadeAppForm.getStagNo());
            facadeTransLog.setAppNo(facadeAppForm.getAppNo());
            // 添加交易表
            facadeTransLog.setRequestXml(requestXml);
            facadeTransLog.setRequestDate(new Date());
            logger.info("交易处理中...");
            responseXml = HttpConnectorUtil.interaction(
                    Config.getProp(trialUrl), requestXml,
                    facadeAppForm.getPartnerNo(), transCode);
            logger.info("试算接口响应报文：-------------------->" + responseXml);
            // 请求交易系统
            if (StrUtil.isNotEmpty(responseXml)) {
                backMessage = getResponseXml(responseXml);
                // 保费计算调用成功
                if (statusCode.equals(backMessage.get("RESULTCODE"))) {
                    // 总保费
                    String TOTALPREMIUM = backMessage.get("TOTALPREMIUM");
                    // 总保额
                    String TOTALAMOUNT = backMessage.get("TOTALAMOUNT");
                    // 不含税总保费
                    String TOTALPREMIUMNOTAX = (backMessage
                            .get("TOTALPREMIUMNOTAX") == "" ? "0.00"
                            : backMessage.get("TOTALPREMIUMNOTAX"));
                    // 总增值税
                    String TOTALPREMIUMVAT = (backMessage
                            .get("TOTALPREMIUMVAT") == "" ? "0.00"
                            : backMessage.get("TOTALPREMIUMVAT"));
                    // 单个保费
                    String SINGLEPREMIUM = backMessage.get("SINGLEPREMIUM");
                    // 单个保额
                    String SINGLEAMOUNT = backMessage.get("SINGLEAMOUNT");

                    facadeAppForm.setTotPremamt(new BigDecimal(TOTALPREMIUM));
                    facadeAppForm
                            .setPremNotax(new BigDecimal(TOTALPREMIUMNOTAX));
                    facadeAppForm.setPremVat(new BigDecimal(TOTALPREMIUMVAT));
                    facadeAppForm.setInsAmount(new BigDecimal(TOTALAMOUNT));
                    facadeAppForm.setSingleAmount(new BigDecimal(SINGLEAMOUNT));
                    facadeAppForm
                            .setSinglePremium(new BigDecimal(SINGLEPREMIUM));
                    facadeAppFormService.updateFacadeAppForm(facadeAppForm);
                }
                facadeAppForm.setResultCode(backMessage.get("RESULTCODE"));
                facadeAppForm.setErrInfo(backMessage.get("ERRINFO"));
                if(backMessage.get("WARNINFO")!=null){
                	 facadeAppForm.setWarnInfo(backMessage.get("WARNINFO"));
                }
                facadeTransLog.setResultCode(backMessage.get("RESULTCODE"));
                facadeTransLog.setResultDesc(backMessage.get("ERRINFO"));
            } else {
                logger.info("投保单号:[" + facadeAppForm.getAppNo() + "]保费计算连接失败");
                facadeTransLog.setResultCode("-1");
                facadeTransLog.setResultDesc("连接失败");

                facadeAppForm.setResultCode("-1");
                facadeAppForm.setErrInfo("连接失败");
            }
        } catch (Exception e) {
            logger.error("保费计算异常", e);
            throw e;
        } finally {
            // 缴费后更新交易记录表信息
            facadeTransLog.setResponseXml(responseXml);
            facadeTransLog.setResponseDate(new Date());
            facadePayDao.insertFacadeTransLog(facadeTransLog);
            logger.info("投保单:[" + facadeAppForm.getAppNo() + "]保费计算处理结束");
        }

        return facadeAppForm;
    }

    /**
     * 
     * @param responseXml
     * @return 返回解析后的报文集合
     * @throws UnsupportedEncodingException
     */
    private Map<String, String> getResponseXml(String responseXml)
            throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        try {
            Document document = DocumentHelper.parseText(responseXml);
            Element root = document.getRootElement();
            // 返回码
            String RESULTCODE = root.selectSingleNode(
                    "/INSUREQRET/HEAD/RESULTCODE").getText();
            map.put("RESULTCODE", RESULTCODE);
            // 返回信息
            String ERRINFO = root.selectSingleNode("/INSUREQRET/HEAD/ERRINFO") != null ? root
                    .selectSingleNode("/INSUREQRET/HEAD/ERRINFO").getText()
                    : "";

            // 防止交易系统异常后错误信息过长
            if (ERRINFO.getBytes("gbk").length > 300) {
                map.put("ERRINFO", ERRINFO.substring(0, 150));
            } else {
                map.put("ERRINFO", ERRINFO);
            }
            // 交易码
            String TRANSRNO = root
                    .selectSingleNode("/INSUREQRET/HEAD/TRANSRNO") != null ? root
                    .selectSingleNode("/INSUREQRET/HEAD/TRANSRNO").getText()
                    : "";
            map.put("TRANSRNO", TRANSRNO);
            // 交易系统投保单号
            String APPNO = root.selectSingleNode("/INSUREQRET/MAIN/APPNO") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/APPNO").getText() : "";
            map.put("APPNO", APPNO);
            // 交易系统保单号
            String POLNO = root.selectSingleNode("/INSUREQRET/MAIN/POLNO") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/POLNO").getText() : "";
            map.put("POLNO", POLNO);
            // 交易系统电子保单链接
            String EURL = root.selectSingleNode("/INSUREQRET/MAIN/EURL") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/EURL").getText() : "";
            map.put("EURL", EURL);
            // 含税保费
            String TOTALPREMIUM = root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUM") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUM")
                    .getText() : "";
            map.put("TOTALPREMIUM", TOTALPREMIUM);
            // 不含税保费
            String TOTALPREMIUMNOTAX = root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUMNOTAX") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUMNOTAX")
                    .getText() : "";
            map.put("TOTALPREMIUMNOTAX", TOTALPREMIUMNOTAX);
            // 增值税额
            String TOTALPREMIUMVAT = root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUMVAT") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALPREMIUMVAT")
                    .getText() : "";
            map.put("TOTALPREMIUMVAT", TOTALPREMIUMVAT);
            // 总保额
            String TOTALAMOUNT = root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALAMOUNT") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/TOTALAMOUNT").getText()
                    : "";
            map.put("TOTALAMOUNT", TOTALAMOUNT);
            // 单个保费
            String SINGLEPREMIUM = root
                    .selectSingleNode("/INSUREQRET/MAIN/SINGLEPREMIUM") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/SINGLEPREMIUM")
                    .getText() : "";
            map.put("SINGLEPREMIUM", SINGLEPREMIUM);
            // 单个保额
            String SINGLEAMOUNT = root
                    .selectSingleNode("/INSUREQRET/MAIN/SINGLEAMOUNT") != null ? root
                    .selectSingleNode("/INSUREQRET/MAIN/SINGLEAMOUNT")
                    .getText() : "";
            map.put("SINGLEAMOUNT", SINGLEAMOUNT);
            // 黑名单信息
            String WARNINFO = root
            		.selectSingleNode("/INSUREQRET/MAIN/WARNINFO") != null ? root
            				.selectSingleNode("/INSUREQRET/MAIN/WARNINFO")
            				.getText() : "";
            map.put("WARNINFO", WARNINFO);
        } catch (DocumentException e) {
            map.put("RESULTCODE", "-1");
            map.put("ERRINFO", "报文解析错误");
            logger.error("异常:[报文解析错误]", e);
        }
        return map;
    }
    
    /**
     * 装配投被保受益人信息
     * 
     * @param facadeAppForm
     * @return
     * @throws Exception
     */
    private Map<String, Object> createFacadeAppForm(FacadeAppForm facadeAppForm)
            throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        map.put("appNo", facadeAppForm.getAppNo());
        // 被保人列表
        List<FacadeAppInsured> facadeAppInsureds = facadeAppInsuredDao
                .selectFacadeAppInsuredList(map);

        // 投保人
        FacadeAppApplicant facadeAppApplicant = facadeAppApplicantDao
                .selectFacadeAppApplicantByMap(map);
        map = new HashMap<String, String>();
        //激活卡法定受益人
//        // 受益人列表
//        for (int i = 0; i < facadeAppInsureds.size(); i++) {
//            FacadeAppInsured facadeAppInsured = facadeAppInsureds.get(i);
//            map.put("insuredClientNo", facadeAppInsured.getClientNo());
//            List<FacadeAppBeneficiary> facadeAppBeneficiarys = facadeAppBeneficiaryDao
//                    .selectFacadeAppBeneficiaryByMap(map);
//            if (null != facadeAppBeneficiarys
//                    && facadeAppBeneficiarys.size() > 0) {
//                facadeAppInsured
//                        .setFacadeAppBeneficiarys(facadeAppBeneficiarys);
//                facadeAppInsureds.set(i, facadeAppInsured);
//            }
//        }
        // 处理投保单的完整状态
        Map<String, Object> mapParam = new HashMap<String, Object>();
        mapParam.put("facadeAppForm", facadeAppForm);
        mapParam.put("facadeAppInsureds", facadeAppInsureds);
        mapParam.put("facadeAppApplicant", facadeAppApplicant);
        return mapParam;
    }
}
